﻿#include "pch.h"

namespace logging = boost::log;

DYNLIB_HANDLE hAnalysis = NULL;

bool load_analysis_dll()
{
    if (hAnalysis == NULL)
    {
        try
        {
            init_logging();
#ifdef _WINDOWS
            hAnalysis = DYNLIB_LOAD("analysis.dll");
#else
            hAnalysis = DYNLIB_LOAD("libanalysis.so");
#endif
            STD_COUT << "DLL_PROCESS_ATTACH hAnalysis=" << hAnalysis << STD_ENDL;
            if (hAnalysis == NULL)
            {
                STD_CERR << "Load Library analysis.dll failed." << STD_ENDL;
            }
        }
        CATCH_AND_RETURN(false);
    }
    return true;
}

#ifdef _WINDOWS
BOOL APIENTRY DllMain(HMODULE hModule, DWORD ul_reason_for_call, LPVOID lpReserved)
{
    switch (ul_reason_for_call)
    {
    case DLL_PROCESS_ATTACH:
        load_analysis_dll();
        break;
    case DLL_THREAD_ATTACH:
        STD_COUT << "DLL_THREAD_ATTACH" << STD_ENDL;
        break;
    case DLL_THREAD_DETACH:
        STD_COUT << "DLL_THREAD_DETACH" << STD_ENDL;
        break;
    case DLL_PROCESS_DETACH:
        std::cout << "DLL_THREAD_DETACH" << std::endl;
        break;
    }
    return TRUE;
}
#else
void __attribute__((constructor)) onProcessAttach()
{
    STD_COUT << "Library is being loaded (similar to DLL_PROCESS_ATTACH)" << STD_ENDL;
    load_analysis_dll();
}
void __attribute__((destructor)) onProcessDetach()
{
    STD_COUT << "Library is being unloaded (similar to DLL_PROCESS_DETACH)" << STD_ENDL;
}
#endif

BRIDGE6DLL_API bool testDLL()
{
    STD_COUT << "testDLL: " << STD_ENDL;
    std::shared_ptr<TOrgFile> p1;
    std::shared_ptr<TOrgFile> p2 = std::make_shared<TOrgFile>();
    int64_t *i1 = (int64_t *)&p1;
    int64_t *i2 = (int64_t *)&p2;
    STD_COUT << "sizeof(TPRGPARA): " << sizeof(TPRGPARA) << STD_ENDL;
    STD_COUT << "sizeof(AUTOPOOL): " << sizeof(AUTOPOOL) << STD_ENDL;
    STD_COUT << "sizeof(AUTOPARA): " << sizeof(AUTOPARA) << STD_ENDL;
    STD_COUT << "sizeof(TDLLMETRIC): " << sizeof(TDLLMETRIC) << STD_ENDL;
    STD_COUT << "sizeof(TUkPkFactor): " << sizeof(TUkPkFactor) << STD_ENDL;
    STD_COUT << "sizeof(TIPara): " << sizeof(TIPara) << STD_ENDL;
    STD_COUT << "sizeof(AUTOIPARA): " << sizeof(AUTOIPARA) << STD_ENDL;
    STD_COUT << "sizeof(TEPara): " << sizeof(TEPara) << STD_ENDL;
    STD_COUT << "----------------------------------------" << STD_ENDL;
    STD_COUT << "sizeof(TDLLTPRGListItem):" << sizeof(TDLLTPRGListItem) << STD_ENDL;
    STD_COUT << "sizeof(TDLLTPRGINF):" << sizeof(TDLLTPRGINF) << STD_ENDL;
    STD_COUT << "sizeof(TDLLIPINF):" << sizeof(TDLLIPINF) << STD_ENDL;
    STD_COUT << "sizeof(TSegCalibItem):" << sizeof(TSegCalibItem) << STD_ENDL;
    STD_COUT << "sizeof(TDLLIDTListItem):" << sizeof(TDLLIDTListItem) << STD_ENDL;
    STD_COUT << "sizeof(TDLLIDTINF):" << sizeof(TDLLIDTINF) << STD_ENDL;
    STD_COUT << "sizeof(TDLLResultListItem):" << sizeof(TDLLResultListItem) << STD_ENDL;
    STD_COUT << "sizeof(TDLLRESINF):" << sizeof(TDLLRESINF) << STD_ENDL;
    STD_COUT << "sizeof(TRAWBAG):" << sizeof(TRAWBAG) << STD_ENDL;
    STD_COUT << "sizeof(TSMPBAG):" << sizeof(TSMPBAG) << STD_ENDL;
    STD_COUT << "sizeof(TSTDAMTListItem):" << sizeof(TSTDAMTListItem) << STD_ENDL;
    STD_COUT << "sizeof(TAMTINF):" << sizeof(TAMTINF) << STD_ENDL;
    STD_COUT << "sizeof(TSTDCPTListItem):" << sizeof(TSTDCPTListItem) << STD_ENDL;
    STD_COUT << "sizeof(TCPTINF):" << sizeof(TCPTINF) << STD_ENDL;
    STD_COUT << "sizeof(TDLLSTDINF):" << sizeof(TDLLSTDINF) << STD_ENDL;
    STD_COUT << "sizeof(TDLLGROUPListItem):" << sizeof(TDLLGROUPListItem) << STD_ENDL;
    STD_COUT << "sizeof(TDLLGRPINF):" << sizeof(TDLLGRPINF) << STD_ENDL;
    STD_COUT << "sizeof(TDLLEPINF):" << sizeof(TDLLEPINF) << STD_ENDL;
    STD_COUT << "sizeof(TMiscellaneous):" << sizeof(TMiscellaneous) << STD_ENDL;
    STD_COUT << "----------------------------------------" << STD_ENDL;
    STD_COUT << "sizeof(TFileItem):" << sizeof(TFileItem) << STD_ENDL;
    STD_COUT << "sizeof(TSample):" << sizeof(TSample) << STD_ENDL;
    STD_COUT << "sizeof(TInject):" << sizeof(TInject) << STD_ENDL;
    STD_COUT << "sizeof(TInstHead):" << sizeof(TInstHead) << STD_ENDL;
    STD_COUT << "sizeof(TOvenCond):" << sizeof(TOvenCond) << STD_ENDL;
    STD_COUT << "sizeof(TInletCond):" << sizeof(TInletCond) << STD_ENDL;
    STD_COUT << "sizeof(TColumnCond):" << sizeof(TColumnCond) << STD_ENDL;
    STD_COUT << "sizeof(TDetectCond):" << sizeof(TDetectCond) << STD_ENDL;
    STD_COUT << "sizeof(TAuxCond):" << sizeof(TAuxCond) << STD_ENDL;
    STD_COUT << "sizeof(TPumpCond):" << sizeof(TPumpCond) << STD_ENDL;
    STD_COUT << "sizeof(TRampItem):" << sizeof(TRampItem) << STD_ENDL;
    STD_COUT << "sizeof(TPumpGradItem):" << sizeof(TPumpGradItem) << STD_ENDL;
    STD_COUT << "sizeof(TWaveLengthItem):" << sizeof(TWaveLengthItem) << STD_ENDL;
    STD_COUT << "sizeof(TFloatRampItem):" << sizeof(TFloatRampItem) << STD_ENDL;
    STD_COUT << "sizeof(TAuxCondEx):" << sizeof(TAuxCondEx) << STD_ENDL;
    STD_COUT << "sizeof(TInstCond):" << sizeof(TInstCond) << STD_ENDL;
    STD_COUT << "sizeof(TAnalResult):" << sizeof(TAnalResult) << STD_ENDL;
    STD_COUT << "sizeof(TSynResult):" << sizeof(TSynResult) << STD_ENDL;
    STD_COUT << "sizeof(TEventList):" << sizeof(TEventList) << STD_ENDL;
    STD_COUT << "sizeof(TCompList):" << sizeof(TCompList) << STD_ENDL;
    STD_COUT << "sizeof(TGroupList):" << sizeof(TGroupList) << STD_ENDL;
    STD_COUT << "sizeof(TSegmentItem):" << sizeof(TSegmentItem) << STD_ENDL;
    STD_COUT << "sizeof(TSegmentList):" << sizeof(TSegmentList) << STD_ENDL;
    STD_COUT << "sizeof(TCalibHead):" << sizeof(TCalibHead) << STD_ENDL;
    STD_COUT << "sizeof(TCalibList):" << sizeof(TCalibList) << STD_ENDL;
    STD_COUT << "sizeof(TCalibResult):" << sizeof(TCalibResult) << STD_ENDL;
    STD_COUT << "sizeof(TRawItem):" << sizeof(TRawItem) << STD_ENDL;
    STD_COUT << "sizeof(TMethodHead):" << sizeof(TMethodHead) << STD_ENDL;
    STD_COUT << "sizeof(TOrgHead):" << sizeof(TOrgHead) << STD_ENDL;
    STD_COUT << "sizeof(TMethodFile):" << sizeof(TMethodFile) << STD_ENDL;
    STD_COUT << "sizeof(TOrgFile):" << sizeof(TOrgFile) << STD_ENDL;
    STD_COUT << "----------------------------------------" << STD_ENDL;
    STD_COUT << "sizeof(std::shared_ptr<TMethodFile>): " << sizeof(std::shared_ptr<TMethodFile>) << STD_ENDL;
    STD_COUT << "sizeof(std::shared_ptr<TOrgFile>): " << sizeof(std::shared_ptr<TOrgFile>) << STD_ENDL;
    STD_COUT << "*i1: " << std::hex << *i1 << STD_ENDL;
    STD_COUT << "*i2: " << std::hex << *i2 << STD_ENDL;
    STD_COUT << "p1.get(): " << p1.get() << STD_ENDL;
    STD_COUT << "p2.get(): " << p2.get() << STD_ENDL;
    STD_COUT << "p1.use_count(): " << p1.use_count() << STD_ENDL;
    STD_COUT << "p2.use_count(): " << p2.use_count() << STD_ENDL;
    STD_COUT << "getExecutableDirectory:" << getExecutableDirectory() << STD_ENDL;
    STD_COUT << "getModulePath:" << getModulePath() << STD_ENDL;

    return true;
}

// 3.2.1、获取错误码
int32_t getLastErrorCode()
{
    int32_t code;
    char *pMessage;
    get_error(&code, &pMessage);
    return code;
}

// 3.2.2、获取错误信息
char *getLastErrorMessage()
{
    int32_t code;
    char *pMessage;
    static char strBlank[] = "";
    get_error(&code, &pMessage);
    if (pMessage == nullptr)
    {
        return strBlank;
    }
    return pMessage;
}

// 3.2.3、初始化文件系统
bool initBridgeAnalysis(const char *szConfigFile)
{
    return true;
}

std::mutex sampling_instance_mutex;

// 3.2.4、开始采样
bool startSample(int64_t nHandle)
{
    std::lock_guard<std::mutex> lock(sampling_instance_mutex);
    bool innerCall = false;

    clear_error();
    CHECK_ORG_HANDLE(nHandle);
    if (channel_sampling && channel_sampling.get()->isOrgHandleSampling(nHandle))
    {
        SET_ERROR(ERR_CODE_ORG_HANDLE_IS_SAMPLING, ERR_MESSAGE_ORG_HANDLE_IS_SAMPLING, nHandle);
        return false;
    }
    else if (channel_sampling)
    {
        SET_ERROR(ERR_CODE_CHANNEL_IS_SAMPLING, ERR_MESSAGE_CHANNEL_IS_SAMPLING);
        return false;
    }

    try
    {
        TChannelSampling::SamplingConfig samplingConfig;
        samplingConfig.redis_timeout_msec = 5000;     // Redis超时N1毫秒未收到数据异常
        samplingConfig.start_timeout_msec = 5000;     // 启动采样N2毫秒内数据未切变采样状态
        samplingConfig.stop_timeout_msec = 5000;      // 停止采样N3毫秒内数据未切变基线状态
        samplingConfig.stop_time_sync_msec = 5000;    // 停止时间与当前时间不同步，差异超N4毫秒
        samplingConfig.gatcher_time_sync_msec = 5000; // 采样时长与方法时长不同步，差异超N5毫秒
        channel_sampling = std::make_unique<TChannelSampling>(samplingConfig);
        channel_sampling->setOrgHandle(nHandle);
        channel_sampling->StartSampling();
        if (channel_sampling->hasError())
        {
            SET_ERROR(channel_sampling->getLastErrorCode(), channel_sampling->getLastErrorMessage().c_str());
            channel_sampling.reset();
            return false;
        }
        return true;
    }
    catch (const std::exception &e)
    {
        SET_ERROR(ERR_CODE_SAMPLING_START_FAILED, ERR_MESSAGE_SAMPLING_START_FAILED, e.what());
        channel_sampling.reset();
        return false;
    }
}

// 3.2.5、停止采样
bool stopSample(int64_t nHandle)
{
    std::lock_guard<std::mutex> lock(sampling_instance_mutex);
    bool innerCall = false;

    clear_error();
    CHECK_ORG_HANDLE(nHandle);

    if (!channel_sampling)
    {
        SET_ERROR(ERR_CODE_CHANNEL_IS_NOT_SAMPLING, ERR_MESSAGE_CHANNEL_IS_NOT_SAMPLING);
        return false;
    }
    else if (!channel_sampling.get()->isOrgHandleSampling(nHandle))
    {
        SET_ERROR(ERR_CODE_ORG_HANDLE_IS_NOT_SAMPLING, ERR_MESSAGE_ORG_HANDLE_IS_NOT_SAMPLING, nHandle);
        return false;
    }

    try
    {
        bool ret = channel_sampling->StopSampling();
        channel_sampling.reset();
        return ret;
    }
    catch (const std::exception &e)
    {
        SET_ERROR(ERR_CODE_SAMPLING_STOP_FAILED, ERR_MESSAGE_SAMPLING_STOP_FAILED, e.what());
        channel_sampling.reset();
        return false;
    }
}

bool _wildcardMatch(const std::string &str, const std::string &pattern)
{
    std::string::const_iterator strIt = str.begin();
    std::string::const_iterator patIt = pattern.begin();
    std::string::const_iterator strSaved = str.end();
    std::string::const_iterator patSaved = pattern.end();

    while (strIt != str.end())
    {
        if (patIt != pattern.end() && *patIt == '*')
        {
            patSaved = patIt++;
            strSaved = strIt;
        }
        else if (patIt != pattern.end() && (*patIt == '?' || tolower(*patIt) == tolower(*strIt)))
        {
            ++patIt;
            ++strIt;
        }
        else if (patSaved != pattern.end())
        {
            patIt = patSaved + 1;
            strIt = ++strSaved;
        }
        else
        {
            return false;
        }
    }

    while (patIt != pattern.end() && *patIt == '*')
    {
        ++patIt;
    }

    return patIt == pattern.end();
}

// 3.3.1、获取文件列表
bool getFileList(const char *szFullPath, bool includeSubDir, TFileItem *pBuffer, int32_t nBufferCount, int32_t *pDataCount, const char *pchWildcard)
{
    boost::filesystem::path path(szFullPath);
    try
    {
        clear_error();
        *pDataCount = 0;
        for (const auto &iter : boost::filesystem::directory_iterator(path))
        {
            TFileItem fileItem;
            boost::filesystem::path p = iter.path();
            std::string fullPathName = p.string();
            std::string fileNameWithExt = p.filename().string();
            std::string fileNameWithoutExt = p.stem().string();
            std::string extName = p.extension().string();
            std::string fileName = fileNameWithoutExt;
            if (boost::filesystem::exists(p))
            {
#ifdef PLATFORM_WINDOWS
                fileItem.createTime = boost::filesystem::creation_time(p);
#else
                fileItem.createTime = boost::filesystem::last_write_time(p);
#endif
                fileItem.modifyTime = boost::filesystem::last_write_time(p);
                if (boost::filesystem::is_directory(iter.path()))
                {
                    fileItem.isFolder = true;
                    fileItem.fileSize = 0;
                    fileName = fileNameWithExt;
                    extName = "";
                    if (!includeSubDir)
                    {
                        continue;
                    }
                }
                else
                {
                    fileItem.isFolder = false;
                    fileItem.fileSize = boost::filesystem::file_size(p);
                }
                STRING_COPY(fileName.c_str(), fileItem.fileName);
                STRING_COPY(extName.c_str(), fileItem.extName);
                if (_wildcardMatch(fileNameWithExt, pchWildcard))
                {
                    if (*pDataCount < nBufferCount)
                    {
                        BYTE_COPY(&fileItem, pBuffer, sizeof(TFileItem));
                    }
                    (*pDataCount)++;
                }
            }
        }
        if (*pDataCount > nBufferCount)
        {
            SET_ERROR(ERR_CODE_BUFFER_INSUFFICIENT, ERR_MESSAGE_BUFFER_INSUFFICIENT, "pBuffer", 1L * sizeof(TFileItem) * nBufferCount, 1L * sizeof(TFileItem) * *pDataCount);
            return false;
        }
    }
    CATCH_AND_RETURN(false);
    return true;
}

// 3.3.2、删除指定文件
bool deleteFile(const char *szFullName)
{
    try
    {
        clear_error();
        boost::filesystem::path filePath(szFullName);

        // 检查文件是否存在
        if (!boost::filesystem::exists(filePath))
        {
            SET_ERROR(ERR_CODE_FILE_NOT_EXISTS, ERR_MESSAGE_FILE_NOT_EXISTS, szFullName);
            return false;
        }

        // 检查是否是目录
        if (boost::filesystem::is_directory(filePath))
        {
            SET_ERROR(ERR_CODE_FILE_DELETE_FAILED, ERR_MESSAGE_FILE_DELETE_FAILED, szFullName);
            return false;
        }

        // 新增：检查是否为只读文件
        auto perms = boost::filesystem::status(filePath).permissions();
        if ((perms & boost::filesystem::perms::owner_write) == boost::filesystem::perms::no_perms)
        {
            SET_ERROR(ERR_CODE_FILE_DELETE_FAILED, ERR_MESSAGE_FILE_DELETE_FAILED, szFullName);
            return false;
        }

        // 删除文件
        boost::filesystem::remove(filePath);

        // 验证是否删除成功
        if (boost::filesystem::exists(filePath))
        {
            SET_ERROR(ERR_CODE_FILE_DELETE_FAILED, ERR_MESSAGE_FILE_DELETE_FAILED, szFullName);
            return false;
        }
    }
    CATCH_AND_RETURN(false);
    return true;
}

const uint32_t detector_masks[] = {0xff000000, 0x00ff0000, 0x0000ff00, 0x000000ff};
const uint32_t rshift_bits[] = {24, 16, 8, 0};

// 3.3.3、判定信号通道是否有效
bool isValidChannel(uint32_t Detector, int32_t chn)
{
    return getDetectorID(Detector, chn) != -1;
}

// 3.3.3、判定检测器ID是否有效
bool isValidDetectorID(uint32_t Detector, int32_t detID)
{
    return getChannelID(Detector, detID) != -1;
}

// 3.3.4、获取信号通道对应的检测器ID
int32_t getDetectorID(uint32_t Detector, int32_t chn)
{
    if (chn < 0 || chn >= 4)
    {
        return -1;
    }
    int32_t detID = (Detector & detector_masks[chn]) >> rshift_bits[chn];
    if (detID == 0xff)
    {
        return -1;
    }
    return detID;
}

// 3.3.5、获取检测器ID对应的信号通道号
int32_t getChannelID(uint32_t Detector, int32_t detID)
{
    if (detID < 0 || detID >= 0xff)
    {
        return -1;
    }
    for (int32_t chn = 0; chn < 4; chn++)
    {
        if (getDetectorID(Detector, chn) == detID)
        {
            return chn;
        }
    }
    return -1;
}